package com.bluetoothprint;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Context;

public class BluetoothControler {
	private static BluetoothControler blueCon;
	private static Object lock = new Object();
	private static Object connecLock = new Object();
	private static Object writeLock = new Object();
	private BluetoothPrintListener mListener;
	private Context mContext;
	private UUID uuid;
	// private BluetoothAdapter adapter;
	private BluetoothSocket bS;
	private InputStream in;
	private OutputStream out;
	private boolean run;

	public interface BluetoothPrintListener {
		public boolean onStateChange(int currentState);

		public boolean onConnected(String deviceName, String address);

		public boolean onConnectFailed();

		public boolean onConnectedBroken();
	}

	public static BluetoothControler getInstance(Context context,
			BluetoothPrintListener listener) {
		if (blueCon == null) {
			synchronized (lock) {
				if (blueCon == null) {
					blueCon = new BluetoothControler(context, listener);
				}
			}
		}
		blueCon.init(context, listener);
		return blueCon;
	}

	private void init(Context context, BluetoothPrintListener listener) {
		// TODO Auto-generated method stub
		this.mContext = context;
		this.mListener = listener;
		// adapter = BluetoothAdapter.getDefaultAdapter();
	}

	private void setListener(BluetoothPrintListener listener) {
		this.mListener = listener;
	}

	private BluetoothControler(Context context, BluetoothPrintListener listener) {
		init(context, listener);
	}

	public void connect(final BluetoothDevice device) {
		run = true;
		new Thread() {
			public void run() {

				synchronized (connecLock) {

					int i = 0;
					while (run) {
						if (device != null) {

							if (uuid == null)
								uuid = UUID.randomUUID();
							disConnect();
							try {
								// BluetoothSocket socket = device
								// .createRfcommSocketToServiceRecord(uuid);
								BluetoothSocket socket = (BluetoothSocket) (device
										.getClass().getMethod(
										"createRfcommSocket",
										new Class[] { int.class })).invoke(
										device, 1);
								if (socket != null) {
									bS = socket;
									System.out.println("connectstart");
									bS.connect();
									System.out.println("connectend");
									in = bS.getInputStream();
									out = bS.getOutputStream();
									if (mListener != null) {
										System.out.println("onConnected");
										mListener.onConnected(device.getName(),
												device.getAddress());
									}
									break;
								}
							} catch (Exception e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
								disConnect();
								if (i < 0) {
									try {
										sleep(50);
									} catch (InterruptedException e1) {
										// TODO Auto-generated catch block
										e1.printStackTrace();
									}
									continue;
								} else {
									if (mListener != null) {
										System.out.println("onConnectFailed");
										mListener.onConnectFailed();
									}

								}

							}
						}
						System.out.println("i:" + i);
						i++;
					}

				}

			};
		}.start();

	}

	public void write(final byte[] data) {
		new Thread() {
			public void run() {
				synchronized (writeLock) {
					if (out != null) {
						try {
							out.write(data);
							out.flush();
						} catch (IOException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				}
			};
		}.start();

	}

	public void disConnect() {
		run = false;
		if (in != null)
			try {
				in.close();
				in = null;
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		if (out != null)
			try {
				out.close();
				out = null;
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		if (bS != null)
			try {
				bS.close();
				bS = null;
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		System.out.println("disConnect");
	}

	public void destroy() {
		disConnect();
		blueCon = null;
	}
}
